各位看倌還記得02. 看的懂的程式碼,才是好的程式碼看到的程式嗎?
造成程式碼不易閱讀的因素有很多,但最常見的就是命名行為不確實。下面,我們將前文出現的程式碼,擷取一小段落於下方,讓我們來 code review 有那些問題是因為命名行為不確實造成的。
int[,] k111 = k;
Random innerRnd8 = new Random(Guid.NewGuid().GetHashCode());
int a1 = innerRnd8.Next(ggg);
Random innerRnd9 = new Random(Guid.NewGuid().GetHashCode());
int a2 = innerRnd9.Next(ggg);
double rrr = _RRR(k[0, a1], k[1, a1], im_1, im2_1);
double rrr_1 = _RRR(k[0, a2], k[1, a2], im_1, im2_1);
接著將上面程式碼,所使用的函數 _RRR(...) 的宣告也找出來。
int _RRR(int _X, int _Y, int[, ,] im_1, int[, ,] im2_1)
{
...
}
int[,] k111 = k;
在看到變數 k 的當下,很難知道它所代表意思。所以只好再回頭查看 k 這個物件,它儲存了什麼資訊、它有什麼用途。
花費在查詢無意義命名的變數的用途與資訊的時間,就是變向的浪費寶貴的開發時間。
Random innerRnd8 = new Random(Guid.NewGuid().GetHashCode());
int a1 = innerRnd8.Next(ggg);
Random innerRnd9 = new Random(Guid.NewGuid().GetHashCode());
int a2 = innerRnd9.Next(ggg);
double rrr = _RRR(k[0, a1], k[1, a1], im_1, im2_1);
接著,我們從程式碼中,可以得知 a1, a2 儲存的內容是一組亂數資料,這樣的寫法很正常。
但配合變數 k 使用時,在閱讀性上並沒有那麼直覺。
所有的變數名稱,識別性太低,而且無法明確的表示該變數的意義。
另外,ggg 其實是類別的成員,在本來的程式碼中,無法直接辨識變數的屬於區域變數、或是類別成員。
若是類別成員與區域變數無法區分,可能會導致開發時,非預期的 BUG。
double rrr = _RRR(k[0, a1], k[1, a1], im_1, im2_1);
double rrr_1 = _RRR(k[0, a2], k[1, a2], im_1, im2_1);
變數 rrr 代表的意思?函數 _RRR(...) 的功能為何?
不明確的函數名稱,會導致無法從函數名稱直接得知回傳物件的意義。
int _RRR(int _X, int _Y, int[, ,] im_1, int[, ,] im2_1)
{
...
}
其實這跟第一點是相同的,無法直接經由參數的名稱,進一步瞭解到參數的意義,可能會造成需要額外的說明文件或註解。
當我們review 完這段程式碼後,發現 k 是一組長度為 ggg 的二維陣列,實際上它的用途是儲存基因演算法中,所使用的樣本資料。ggg 代表的取樣的數量。
private int ggg = 40;
public int[,] ga(int[,,] im_1, int[,,] im2_1)
{
int[,] k = new int[2, ggg];
...
}
若是將上方的程式碼改為下面的寫法。
private int _sampleAmount = 40;
public int[,] ga(int[,,] im_1, int[,,] im2_1)
{
int[,] sampleGroup = new int[2, _sampleCount];
...
}
這樣的閱讀性是是不是高了一點。
函數 _RRR(...) 的功能,主要是為了找出兩張影像在特定座標位置的誤差量。但是在原本的函數名稱中,很難去表示出該函數的功能目標。
int _RRR(int _X, int _Y, int[, ,] im_1, int[, ,] im2_1)
{
...
}
若是將上方的程式碼改為下面的寫法。
int CalcImageOverlapError(int x, int y, int[, ,] image1, int[, ,] image2)
{
...
}
使用 CalcImgeOverlapError 是否更能快速了解函數的功能與目標。
其實,上面將變數名稱、函數名稱更改為有意義名稱的動作,就是重構的一種行為。